//
//  ZCrypto.h
//  Part of Z-Way.C library
//
//  Created by Poltorak Serguei on 3/31/21.
//
//  Copyright (c) 2021 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zway_crypto_h
#define zway_crypto_h

#if !defined(__CRYPTO_OPENSSL__) && !defined(__CRYPTO_MBEDTLS__)
#define __CRYPTO_OPENSSL__
#endif //! defined(__CRYPTO_OPENSSL__) && !defined(__CRYPTO_MBEDTLS__)

#include "ZPlatform.h"
#if defined(__CRYPTO_OPENSSL__)
#include <openssl/evp.h>
#include <openssl/hmac.h>
#endif // __CRYPTO_OPENSSL__

ZWEXPORT_PRIVATE ZWError __AES(const ZWBYTE *key, size_t key_len, const ZWBYTE *data, ZWBYTE *result);
ZWEXPORT_PRIVATE ZWError __RAND(ZWBYTE *key, int len);
ZWEXPORT_PRIVATE ZWError __SHA1(const void *data, size_t data_len, ZWBYTE *result, size_t result_len);

/**
 * @brief Calculates the hash amount using the MD5 algorithm.
 * 
 * @param[in] d Pointer to data.
 * @param[in] n Data size.
 * @param[out] md A pointer to the buffer where the hash amount will be written, the size must be at least 16 bytes.
 * @return On successful completion, a 'NoError' will be returned.
 */
ZWEXPORT_PRIVATE ZWError _zmd5(const void *d, size_t n, void *md);

#if defined(__CRYPTO_OPENSSL__)
struct __zhmac_ctx
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_MAC_CTX *hmac_ctx;
#else
    HMAC_CTX *hmac_ctx;
#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L
};

typedef struct __zhmac_ctx _zhmac_ctx;

/**
 * @brief Counts the 'HMAC' for the data.
 * 
 * @param[in] name A pointer to the hash algorithm name: 'md5', 'sha1', 'sha256', etc.
 * @param[in] key Pointer to the key for 'HMAC'
 * @param[in] len_key Key size
 * @param[in] data A pointer to the data for which we count 'HMAC'
 * @param[in] len_data Data size.
 * @param[out] signature A pointer to the buffer where the calculated signature will be written.
 * @param[in, out] len_signature A pointer to a variable containing the size of the signature buffer and where the size of the actual signature will be written.
 * @return On successful completion, a 'NoError' will be returned.
 */
ZWEXPORT_PRIVATE ZWError _zhmac(ZWCSTR name, const void *key, size_t len_key, const void *data, size_t len_data, void *signature, size_t *len_signature);

/**
 * @brief Initializes 'HMAC'
 * 
 * @param[out] ctx A pointer to the structure for where the work data is stored.
 * @param[in] name A pointer to the hash algorithm name: 'md5', 'sha1', 'sha256', etc.
 * @param[in] key Pointer to the key for 'HMAC'
 * @param[in] len Key size
 * @return On successful completion, a 'NoError' will be returned.
 */
ZWEXPORT_PRIVATE ZWError _zhmac_init(_zhmac_ctx *ctx, ZWCSTR name, const void *key, size_t len);

/**
 * @brief Updates the calculated 'HMAC' signature
 * 
 * @param[in] ctx A pointer to the structure for where the work data is stored.
 * @param[in] data A pointer to the data for which we count 'HMAC'
 * @param[in] len Data size.
 * @return On successful completion, a 'NoError' will be returned.
 */
ZWEXPORT_PRIVATE ZWError _zhmac_update(_zhmac_ctx *ctx, const void *data, size_t len);

/**
 * @brief Allows you to get a signature and cleans up the resources after yourself.
 * 
 * @param[in] ctx A pointer to the structure for where the work data is stored.
 * @param[out] signature A pointer to the buffer where the calculated signature will be written.
 * @param[in, out] len A pointer to a variable containing the size of the signature buffer and where the size of the actual signature will be written.
 * @return On successful completion, a 'NoError' will be returned.
 */
ZWEXPORT_PRIVATE ZWError _zhmac_final(_zhmac_ctx *ctx, void *signature, size_t *len);
#endif // __CRYPTO_OPENSSL__

#endif// zway_crypto_h
